'''
1.码云
2.mysql数据库配置    :为了在项目中用来储存新闻数据以及用户数据
3.redis配置   ：缓存频率比较高的内容，存储session信息，图片验证码，短信验证码
4.Session和session配置     ：将来用来保存用户的登陆信息
5.CSRFProtect   ：保护app，防止csrf攻击

项目特点：
    -类型是一个新闻类型的网站
    -使用的是前后端不分离的方式开发
    -使用的技术：python3.X + flask + 第三方(sdk云通讯+七牛云)+部署(阿里云)
二.
    1.配置文件的抽取   ：方便今后扩展，维护，管理更加高效
        操作流程：
            -定义了config文件
            -将config类抽取到了config文件
            -提供了三种环境下的配置类信息
            -提供了一个config_dict的统一的入口
    2.初始化信息的抽取  ：将初始化信息抽取到单独的包的文件，方便做统一的管理
        操作流程：
            -将manager中的初始化信息，抽取到info到init文件中
            -定义了一个create_app方法接收一个config_name参数
            -根据config_name加载不同环境下的配置类信息
            -在返回一个完整的app给manager文件
    3.视图函数的抽取   ：视图函数是用来处理对应的业务的，可以有很多，所以应该使用蓝图进行统一管理
        操作流程：
            -创建了modules模块，用来管理所有的蓝图
            -在modules底下创建了index包
            -在index中创建了index_blue包
            -在index中创建index_blue蓝图，创建view文件，并使用index_blue装饰视图函数
            -在create_app方法内部。注册蓝图
    4.循环导包
        在导包的时候有可能会陷入死循环
        在控制台查看，是哪些文件产生的循环，点开他们，先办法断掉其中的一环就可以了
    5.redis储存设置
        问题：
            -redis创建在了create_app方法内部。外界不能导入使用
            -在create_app外面创建一个空的redis
        解决：
            -使用 global把create_app中的redis变成全局变量就可以了
    6.日志信息集成
        目的：
            -记录用户的行为
            -记录分析软件的问题
            -便于给产品经理提供设计依据
        流程：
            -定义好log_file方法，拷贝日志记录方法进来
            -在create_app中调试试用即可
    7.日志配置抽取
        目的：为了便于去管理，不同环境下的日志级别
        操作流程：
            1.在config配置文件中，给DevelopConfig,ProductConfig设置不同的级别
            在调用create_app方法的时候。传递对应环境的key值
            取出对应环境下的日志级别，将日志级别传递到log_file方法中
    8.gitkeep忽略日志文件
        目的：课题让logs空文件被提交到git仓库
    9.表结构分析
        目的：主要是了解这个项目中主要的7张表的关系
        注意点：我保存在了手机上，表的关系



三.
    1.数据库的迁移
        目的：将模型类成数据库的具体表格
        操作流程：
            -把models,constants文件拷贝到info中
            -将create_app中的Sqlalchemy(app)改成两句话
                1.create_app方法外部的   db = Sqlalchemy()
                2.create_app方法内部的   db.init_app(app)
            -在manager.py文件中进行迁移
                1.导入三个类
                    flask_script 的 Manager
                    flask_migrate 的 Migrate,MigrateCommand
                2.通过 Manager 创建 manager 管理app
                    manager = Manager(app)
                3.使用 Migrate ,关联 app db
                    Migrate(app,db)
                4.给 manager 添加一条操作指令
                    manager.add_command('db',MigrateCommand)
                    以脚本的形式运行得加一个 runserver
                5.相关性的迁移命令：
                    -生成迁移文件夹 【一次就好】
                        python xxx.py db init
                    -将模型类生成迁移脚本  【变化后重复执行】
                        python xxx.py db migrate -m '注释'
                    -将迁移脚本更新到数据库中  【变化后重复执行】
                        python xxx.py db upgrade
    2.静态文件的集成
        目的：为了给用户提供一个访问页面
        操作流程：
            将static文件添加到info里面，然后使用git管理起来
            #TODO 我还没有git，网不行去学校了之后装起来
    3.首页显示
        目的：用户在访问首页的时候给用户提供一个完整的页面
        操作步骤：
            -在info中，创建templates文件夹
            -将static/news中的index.html拖入到template/news文件中
            在访问根路径的时候使用render_template将index_html网页渲染
    4.网站logo显示
        目的：显示网站的标识，显示在title中
        注意点：
            -当浏览器访问每个网站的时候都会自动请求这个接口——/favicon.ico接口
            -只需要在程序中，写上/favicon.ico的接口，然后返回一张图片即可
            -在flask中需要使用current_app.send_static_file('文件名')
                send_static_file('文件1')，该方法会自动去static静态文件夹中寻找文件1
    5.图片验证码分析
        为了保证注册，登陆的用户是一个真实的用户在操作，为了去获取短信验证码
        注意点：
            -在服务器内部保存图片验证码的时候，前端需要带一个随机字符串（uuid）过来
            -uuid作为key，图片验证码的值作为value储存
    6.图片验证码分析
        目的：便于程序调试，生成图片验证码
        操作流程：
            在info中创建utils包.将captch导入即可
    7.图片验证码视图函数
        目的：为了方便前端调用.获取图片验证码
        操作流程：
            创建新的包passport
            在里面创建新的蓝图
    8.图片验证码去重完善
        目的：不能在服务端储存多份图片，容易导致后端的空间不足
        操作流程：
            -获取参数cur_id，pre_id
            -调用captcha.generate_captcha()函数生成验证码
            -判断是否有上一次图片验证码，如果有就删除
            -返回一张图片，并指定图片格式


四.
    1.短信验证码分析
        目的：为了校验是一个真实的用户，便于用户注册
        注意点：
            -在获取短信验证码的时候需要携带参数：手机号，随机字符串(uuid)，图片验证码
            -发短信用：云通信发送
    2.云通信集成
        目的：能够使用云通讯发送短信
        操作步骤：
            -先注册云通信
            -找到官方的demo实例下载
            -拷贝模板代码到自己的文件中
            -调用单例对象方法，发送短信即可
    3.短信验证码接口
        目的：当前端的页面，点击获取短信验证码的时候能够获取一条短信
        操作流程：
            -获取参数
            -校验参数，图片验证码
            -校验参数，手机号格式
            -发送短信，调用封装好的cpp
            -返回发送的状态
    4.短信验证码完善
        目的：完善接口
        操作流程：
            1.获取参数
            2.参数的为空校验
            3.校验手机的格式
            4.通过图片验证码编号获取图片验证码
            5.判断图片验证码是否过期
            6.判断图片验证码是否正确
            7.删除redis中的图片验证码
            8.生成随机的6位整数，调用CCP发送短信，判断是否发送成功
            9.将短信保存在redis中
            10.返回响应
    5.注册用户接口
        目的创建一个用户保存在数据库中
        操作流程：
            1.获取参数
            2.校验参数，为空校验
            3.手机号作为key取出短信验证码
            4.判断验证码是否过期
            5.判断验证码是否正确
            6.删除redis中的短信
            7.创建用户对象
            8.设置用户对象的属性
            9.保存用户到数据库
            10.返回响应
    6.注册接口完善：
        目的：减少代码
        操作流程：
        # request_data = request.data
        # dict_data = json.loads(request_data)
        # dict_data = request.json  # 和上面两句话相同 还有一个方法也相同：get_json()
    7.注册用户密码加密
        目的：使用flask中提供的安全模块，将密码进行加密
        注意点：
            使用@property装饰的方法，可以当成属性使用，比如print(user.password)
            @.setter给方法增加一个设置方式
            使用了系统的generate_password_hash的方法加密，使用的是sha256算法加密
            系统提供的传递密码的方法，check_password_hash，传递密文和明文，返回TRUE或者FALSE
    8.登陆用户
        操作流程：
            1.获取参数
            2.校验参数，为空校验
            3.通过手机号到数据库查询用户是否存在
            4.判断用户是否存在
            5.校验密码是否正确
            6.将用户的信息保存在session中
            7.返回响应值
    9.登录后右上角显示状态
        操作流程：
            用户登录后，将session信息已经储存在redis中，通过首页获取session中的值
            然后将用户的字典数据，携带到index.html中
            1.获取用户登陆信息
            2.通过user_id获取对象
            3.拼接用户数据渲染页面
            4.传递参数data
    10.推出用户
        操作流程：
            1.清楚用户的session
            2.返回值
    11.记录用户最后一次登陆时间

    12.自动提交
        目的：在flask通过sqlalchemy的属性配置，让数据库能够自动提交
        操作流程：
            在config的配置文件中，设置sqlalchemy_commit_on_teardown = TRUE
            设置好了之后，当数据库的内容改变之后，视图函数在结束的时候就会自动提交
    13.CSRFprotect校验开启
        目的在前端当中携带csrf_token,以便csrf的校验能够通过
        校验过程：
            如果是非表单提交(ajax)
                在cookie中设置csrf_token(自己做)
                在请求头中设置csrf_token(自己做)
                服务器：取出二者进行校验（服务器做的，#TODO 项目倒数第二天分析源代码
            表单提交：
                在表单设置一个影藏的字段保存csrf_token
    14.热门新闻排行
        方法一：
            在index.heml文件中
        方法二：
            {{ loop.index | my_filter }}
            自定义一个过滤器 commons.py
            把函数添加到系统默认的过滤器中
    15.分类数据展示
        目的：在首页的头部展示分类信息
        操作流程
            1.在根路径中查询所有的分类数据
            2.将分类数据转换成查询列表
            3.携带分类数据渲染页面
    16.首页新闻列表展示
        目的：编写新闻展示列表获取新闻数据，展示在首页中
        操作步骤：
            1.获取参数
            2.参数类型转换
            3.分页查询
            4.获取分页对象中的属性，当前页，总页数，当前页的对象列表
            5.将对象列表转换成字典列表
            6.携带参数返回响应
    17.新闻列表更多加载调试

    18.分页切换调试

    19.新闻蓝图创建
        目的：创建新闻蓝图对象管理新闻页面
        操作流程：
            蓝图使用三部曲
    20.新闻详情页的展示
    21.基类模板抽取，首页页面继承
    22.新闻详情页的继承base
    23.新闻详情页用户数据，热门新闻展示

    24.使用g对象配合装饰器使用
        装饰器作用：给已经存在的方法添加额外的功能，而不应该改变原有的结构
        解决办法：不改变原有函数结构，functools.wraps可以解决该问题
        减少代码的冗余
    25.登陆框和评论框的展示
        操作流程：二选一
        data.user_info要是有数据就显示一个
        没有就显示另外一个
    26.显示收藏或者取消收藏按钮
        新闻在用户收藏的所有新闻之中，就传参True,不在就False
    27.新闻收藏&者取消收藏
        思路分析：
            1.判断用户是否登陆了
            2.获取参数
            3.参数校验，为空校验
            4.操作类型校验
            5.根据新闻的编号取出新闻对象
            6.判断新闻对象是否存在
            7.根据操作类型进行收藏&取消收藏操作
            8.返回响应
    28.评论的实现
        接口三要素，返回的参数带到前端的什么地方
            # 判断用户是否登陆
            # 获取请求参数
            # 校验参数，为空校验
            # 根据新闻编号，获取新闻对象
            # 判断新闻是否存在
            # 创建评论对象，设置属性
            # 保存评论对象在数据库中
            # 返回响应
    29.评论的显示
        在看文章的时候就显示评论
        去文章的页面获取参数
            # 获取数据库中该条新闻的所有评论
    30.回复评论调试
    31.父评论内容显示
    32.获取用户对哪些评论点过赞
    33.点赞取消点赞后端完成
    34.点赞取消点赞调试
















'''